import sys
parent_dir = "../pygl"
sys.path.append(parent_dir)
import ctypes
import OpenGL.GL as gl
import glm
import imgui
import numpy as np
from common.app_v2 import App
import pygl

class CubeWindow(App):
    # 初始化着色器，vao vbo等
    def setupVertex(self) -> None:
        gl.glEnable(gl.GL_DEPTH_TEST)
        self.program = pygl.ProgramVF("basic/shaders/cube.vs", 
                                      "basic/shaders/cube.fs")
        cube_width = 0.3
        self.line_color = glm.vec3(1.0, 1.0, 1.0)
        vertices = np.array([
            # 位置                              # 颜色             # 纹理坐标
            # 面 0:
            cube_width, cube_width, cube_width,  1.0, 0.0, 0.0,     1.0, 1.0,
            -cube_width, cube_width, cube_width, 1.0, 0.0, 0.0,    1.0, 0.0,
            cube_width,-cube_width, cube_width,  1.0, 0.0, 0.0,     0.0, 0.0,
            -cube_width,-cube_width, cube_width, 1.0, 0.0, 0.0,    0.0, 1.0,
            # 面 1:
            cube_width, cube_width, cube_width,  0.0, 1.0, 0.0,     1.0, 1.0,
            cube_width,-cube_width, cube_width,  0.0, 1.0, 0.0,     1.0, 0.0,
            cube_width, cube_width,-cube_width,  0.0, 1.0, 0.0,     0.0, 0.0,
            cube_width,-cube_width,-cube_width,  0.0, 1.0, 0.0,     0.0, 1.0,
            # 面 2:
            cube_width, cube_width, cube_width,  0.0, 0.0, 1.0,     1.0, 1.0,
            cube_width, cube_width,-cube_width,  0.0, 0.0, 1.0,     1.0, 0.0,
            -cube_width, cube_width, cube_width, 0.0, 0.0, 1.0,    0.0, 0.0,
            -cube_width, cube_width,-cube_width, 0.0, 0.0, 1.0,    0.0, 1.0,
            # 面 3:
            cube_width, cube_width,-cube_width,  1.0, 1.0, 0.0,     1.0, 1.0,
            cube_width,-cube_width,-cube_width,  1.0, 1.0, 0.0,     1.0, 0.0,
            -cube_width, cube_width,-cube_width, 1.0, 1.0, 0.0,    0.0, 0.0,
            -cube_width,-cube_width,-cube_width, 1.0, 1.0, 0.0,    0.0, 1.0,
            # 面 4
            -cube_width, cube_width, cube_width, 0.0, 1.0, 1.0,     1.0, 1.0,
            -cube_width, cube_width,-cube_width, 0.0, 1.0, 1.0,     1.0, 0.0,
            -cube_width,-cube_width, cube_width, 0.0, 1.0, 1.0,     0.0, 0.0,
            -cube_width,-cube_width,-cube_width, 0.0, 1.0, 1.0,     0.0, 1.0,
            # 面 5:
            cube_width,-cube_width, cube_width,  1.0, 0.0, 1.0,      1.0, 1.0,
            -cube_width,-cube_width, cube_width, 1.0, 0.0, 1.0,     1.0, 0.0,
            cube_width,-cube_width,-cube_width,  1.0, 0.0, 1.0,      0.0, 0.0,
            -cube_width,-cube_width,-cube_width, 1.0, 0.0, 1.0,     0.0, 1.0
        ], dtype=gl.GLfloat)
        self.indices = np.array([
            # 面 0:
            0, 1, 2, # 第一个三角形
            2, 1, 3, # 第一个三角形
            # 面 1:
            4, 5, 6, # 第一个三角形
            6, 5, 7, # 第一个三角形
            # 面 2:
            8, 9, 10, # 第一个三角形
            10, 9, 11, # 第一个三角形
            # 面 3:
            12, 13, 14, # 第一个三角形
            14, 13, 15, # 第一个三角形
            # 面 4:
            16, 17, 18, # 第一个三角形
            18, 17, 19, # 第一个三角形
            # 面 5:
            20, 21, 22, # 第一个三角形
            22, 21, 23, # 第一个三角形
        ], dtype=gl.GLuint)
        self.vao = pygl.VertexArrayObject()
        self.vbo = pygl.VertexBufferObject(vertices)
        self.ebo = pygl.ElementBufferObject(self.indices)
        binding_point = 0
        self.vao.setVertexBuffer(self.vbo, binding_point, 0, 
                                 8 * gl.sizeof(gl.GLfloat))
        self.vao.setElementBuffer(self.ebo)
        attribute_position = pygl.VertexAttribute("position", 0, 3, 
                                                  gl.GL_FLOAT, False, 0)
        attribute_color = pygl.VertexAttribute("color",1, 3, gl.GL_FLOAT, 
                                    False, 3 * gl.sizeof(gl.GLfloat))
        attribute_tex_coord = pygl.VertexAttribute("tex_coord",2, 2, 
                        gl.GL_FLOAT, False, 6 * gl.sizeof(gl.GLfloat))
        self.vao.setVertexAttribute(binding_point, attribute_position)
        self.vao.setVertexAttribute(binding_point, attribute_color)
        self.vao.setVertexAttribute(binding_point, attribute_tex_coord)
        self.rotation = glm.vec3(0.0, 0.0, 0.0)
        self.position = glm.vec3(0.0, 0.0, 0.0)
        self.scale = glm.vec3(1.0, 1.0, 1.0)
        self.use_vertex_color = False
        self.tex = pygl.ImageTexture2D("textures/cratetex.png")   
        self.imgui_window_width = 250
        self.imgui_window_height = 350     

    # 配置imgui界面元素
    def showImGui(self)->None:
        imgui.begin("设置")
        _, self.use_vertex_color = imgui.checkbox("使用顶点颜色", 
                                                  self.use_vertex_color)
        if imgui.button("重置"):
            self.rotation = glm.vec3(0.0, 0.0, 0.0)
            self.position = glm.vec3(0.0, 0.0, 0.0)
            self.scale = glm.vec3(1.0, 1.0, 1.0)
        imgui.text("旋转")
        _, rot = imgui.slider_float3("R", self.rotation.x, self.rotation.y, 
                                     self.rotation.z, 0.0, 360)
        self.rotation = glm.vec3(rot)
        imgui.text("平移")
        _, trans = imgui.slider_float3("T", self.position.x, self.position.y, 
                                       self.position.z, -1.0, 1.0)
        self.position = glm.vec3(trans)
        imgui.text("缩放")
        _, sc = imgui.slider_float3("S", self.scale.x, self.scale.y, 
                                    self.scale.z, 0.2, 1.5)
        self.scale = glm.vec3(sc)
        imgui.text("模型矩阵")
        imgui.begin_table("数据", 4)
        for i in range(4):
            imgui.table_next_row()
            for j in range(4):
                imgui.table_next_column()
                imgui.text(str(self.model[j, i]))
        imgui.end_table()
        imgui.end()       

    # 渲染图形
    def render(self) -> None:
        gl.glClearNamedFramebufferfv(0, gl.GL_COLOR, 0, 
                                     self.background_color.to_tuple())
        gl.glClearNamedFramebufferfv(0, gl.GL_DEPTH, 0, [1.0]); 
        self.program.use()
        translation_matrix = glm.translate(self.position)
        rotation_matrix = glm.rotate(glm.radians(self.rotation.x), 
                                     glm.vec3(1.0, 0.0, 0.0))
        rotation_matrix = glm.rotate(rotation_matrix, 
            glm.radians(self.rotation.y), glm.vec3(0.0, 1.0, 0.0))
        rotation_matrix = glm.rotate(rotation_matrix, 
            glm.radians(self.rotation.z), glm.vec3(0.0, 0.0, 1.0))
        scale_matrix = glm.scale(self.scale)
        self.model = translation_matrix * rotation_matrix * scale_matrix
        view = glm.mat4(1.0)
        view = glm.translate(view, glm.vec3(0.0, 0.0, -3.0))
        projection = glm.perspective(glm.radians(45.0), 
            float(self.width)/self.height, 0.1, 100.0)
        self.program.setUniformMatrix4fv(0, self.model)
        self.program.setUniformMatrix4fv(1, view)
        self.program.setUniformMatrix4fv(2, projection)
        if self.use_vertex_color:
            self.program.setUniform1i(3, 1)
        else:
            self.program.setUniform1i(3, 0)
            self.tex.bind(0)
        self.vao.bind()
        gl.glDrawElements(gl.GL_TRIANGLES,36, gl.GL_UNSIGNED_INT, None)

    # 释放资源
    def cleanup(self) -> None:
        self.tex.delete()
        self.vbo.delete()
        self.ebo.delete()
        self.vao.delete()
        self.program.delete()

if __name__ == "__main__":
    app = CubeWindow(100, 100, 800, 600, "你好，立方体App！")
    app.run()

